﻿using System;
using System.Collections.Generic;
using Google.Apis.Calendar.v3;
using Google.Apis.Calendar.v3.Data;

namespace iCalSync
{
    class IcsEvent : Event
    {

        internal void ParseEvent(ref IEnumerator<String> icsEnum)
        {
            icsEnum.MoveNext();
            string icsLine = string.Empty;
            while ((icsLine = icsEnum.Current) != IcsStrings.IcsEventEnd)
            {
                if (icsLine == null) break;
                if (icsLine.ToUpper().Equals(IcsStrings.IcsAlarmStart))
                {
                    if (Reminders == null) Reminders = new RemindersData();
                    Reminders.UseDefault = false;
                    if (Reminders.Overrides == null) Reminders.Overrides = new List<EventReminder>();
                    EventReminder Al = new EventReminder();
                    Reminders.Overrides.Add(Al);
                    ParseAlarm(ref Al, ref icsEnum);
                }
                ParseIcsLine(icsLine);
                icsEnum.MoveNext();
            }
        }

        private void ParseIcsLine(string icsLine)
        {
            Dictionary<string, string> param = new Dictionary<string, string>();
            var lineParts = icsLine.Split(":".ToCharArray());
            if (lineParts.Length < 2) return;
            string lineValue = icsLine.Substring(lineParts[0].Length + 1);
            var lineHeader = lineParts[0].Split(";".ToCharArray());
            string Header = lineHeader[0].ToUpper();
            for (int i = 1; i < lineHeader.Length; i++)
            {
                var lineParam = lineHeader[i].Split("=".ToCharArray());
                string pHeader = lineParam[0].ToUpper();
                string pValue = lineHeader[i].Substring(lineParam[0].Length + 1);
                if (pValue.StartsWith(char.ConvertFromUtf32(34))) pValue = pValue.Substring(1, pValue.Length - 2);
                param.Add(pHeader, pValue);
            }
            switch (Header)
            {
                case IcsStrings.IcsEventStatus:
                    {
                        Status = lineValue.ToLower();
                        break;
                    }
                case IcsStrings.IcsEventSummaryHeader:
                    {
                        Summary = lineValue;
                        break;
                    }
                case IcsStrings.IcsEventDescriptionHeader:
                    {
                        Description = lineValue;
                        break;
                    }
                case IcsStrings.IcsEventLocation:
                    {
                        Location = lineValue;
                        break;
                    }
                case IcsStrings.IcsEventOrganizer:
                    {
                        Organizer = new OrganizerData();
                        if (param.ContainsKey("CN"))
                        {
                            Organizer.DisplayName = param["CN"];
                        }
                        Organizer.Email = lineValue.Substring("mailto:".Length);
                        break;
                    }
                case IcsStrings.IcsEventDtStartHeader:
                    {
                        Start = new EventDateTime();
                        if (param.ContainsKey("TZID"))
                            Start.TimeZone = param["TZID"];
                        if (param.ContainsKey("VALUE"))
                        {
                            if (param["VALUE"] == "DATE")
                                Start.Date = toDateTime(lineValue);
                        }
                        else
                            Start.DateTime = toDateTime(lineValue);
                        break;
                    }
                case IcsStrings.IcsEventDtEndHeader:
                    {
                        End = new EventDateTime();
                        if (param.ContainsKey("TZID"))
                            End.TimeZone = param["TZID"];
                        if (param.ContainsKey("VALUE"))
                        {
                            if (param["VALUE"] == "DATE")
                                End.Date = toDateTime(lineValue);
                        }
                        else
                            End.DateTime = toDateTime(lineValue);
                        break;
                    }
                case IcsStrings.IcsEventRecurrence:
                    {
                        if (Recurrence == null) Recurrence = new List<string>();
                        Recurrence.Add(Header + ":" + lineValue);
                        break;
                    }
                case IcsStrings.IcsEventTransparency:
                    {
                        Transparency = lineValue.ToLower();
                        break;
                    }
                case IcsStrings.IcsEventClass:
                    {
                        Visibility = lineValue.ToLower();
                        break;
                    }
                case IcsStrings.IcsEventUidHeader:
                    {
                        ICalUID = lineValue;
                        break;
                    }
                case IcsStrings.IcsEventSequence:
                    {
                        Sequence = long.Parse(lineValue);
                        break;
                    }
                case IcsStrings.IcsEventAttendee:
                    {
                        if (Attendees == null) Attendees = new List<EventAttendee>();
                        EventAttendee att = new EventAttendee();
                        att.Email = lineValue.Substring("mailto:".Length);
                        if (param.ContainsKey("CN"))
                        {
                            att.DisplayName = param["CN"];
                        }
                        if (param.ContainsKey("RSVP"))
                        {
                            att.Optional = !(param["RSVP"] == "TRUE");
                        }
                        if (param.ContainsKey("PARTSTAT"))
                        {
                            att.ResponseStatus = param["PARTSTAT"].ToLower();
                        }
                        Attendees.Add(att);
                        break;
                    }
            }
            return;
        }

        internal void ParseAlarm(ref EventReminder Al, ref IEnumerator<string> icsEnum)
        {
            icsEnum.MoveNext();
            string icsLine = string.Empty;
            while ((icsLine = icsEnum.Current) != IcsStrings.IcsAlarmEnd)
            {
                if (icsLine == null) break;

                ParseIcsLineAlarm(ref Al, icsLine);
                icsEnum.MoveNext();
            }
        }

        private void ParseIcsLineAlarm(ref EventReminder Al, string icsLine)
        {
            var lineParts = icsLine.Split(":".ToCharArray());
            if (lineParts.Length < 2) return;
            string lineHeader = lineParts[0].ToUpper();
            string lineValue = icsLine.Substring(lineHeader.Length + 1);

            switch (lineHeader)
            {
                case IcsStrings.IcsAlarmTriggerHeader:
                    {
                        Al.Minutes = long.Parse(lineValue.Substring("-PT".Length + 1, lineValue.Length - "-PT".Length - 2));
                        break;
                    }
                case IcsStrings.IcsAlarmActionHeader:
                    {
                        Al.Method = "popup";
                        break;
                    }
            }
        }

        private string toDateTime(string Dte)
        {
            string Temp = Dte.Substring(0, 4) + "-" + Dte.Substring(4, 2) + "-" + Dte.Substring(6, 2);
            if (Dte.Length == 8)
            {
                return Temp;
            }
            Temp += "T" + Dte.Substring(9, 2) + ":" + Dte.Substring(11, 2) + ":" + Dte.Substring(13, 2);
            if (Dte.EndsWith("Z")) Temp += "Z";
            return Temp;
        }
    }
}
